#ifndef TC_OPHSM_HPP
#define TC_OPHSM_HPP

/** \file OpHsm.hpp
 * Declarations for the class OpHsm (Optimum HSM).
 *
 * (c) Copyright 2003-2006 by Semih Cemiloglu
 * All rights reserved, see COPYRIGHT file for details.
 *
 * $Id: OpHsm.hpp 119 2006-06-21 04:57:25Z semihc $
 *
 *
 */

#ifndef STD_MAP
#define STD_MAP
# include <map>
#endif

#ifndef TC_GLOBAL_HH
# include "Global.hh"
#endif
#ifndef TC_ASSERT_HPP
# include "Assert.hpp"
#endif
#ifndef TC_SMEVENT_HH
# include "SmEvent.hh"
#endif
#ifndef TC_ARRAY_HPP
# include "Array.hpp"
#endif


namespace TC {


  /**
   * A class template to represent HSM state concept.
   * At the heart of this abstraction lies a pointer-to-member
   * object which points to function that in turn returns same
   * type of pointer.
   * See More Exceptional Book, Item 32 for rationale.
   */
  TC_EXPORT template <class H>
  class HsmState
  {
  public:
    // TYPES
    typedef HsmState<H> Ret_t;
    typedef const SmEvent* Arg_t;
    //! Action type is a pointer-to-member function which
    //! also return HsmState object.
    typedef Ret_t (H::*Action_t)(Arg_t); 

    // CREATORS
    //! Default constructor
    HsmState<H>() 
    : m_ptr(0) {}

    //! Construction from the action object
    HsmState<H>(Action_t act)
      : m_ptr(act) {}

    //! Copy constructor
    HsmState<H>(const HsmState<H>& hs)
    { m_ptr = hs.m_ptr; }
      

    // MODIFIERS
    //! Copy assignment
    void operator=(const HsmState<H>& hs)
    { m_ptr = hs.m_ptr; }

    //! To bypass temporary creation
    void operator=(Action_t act) 
    { m_ptr = act; }
    
    
    // ACCESSORS
    Action_t getAction() const
    { return m_ptr; }

    //! Conversion to the Action type (pointer-to-member-function)
    operator Action_t() const 
    { return m_ptr; }

    //! To execute the action associated with the state
    Action_t runAction(H* h, const SmEvent* e) const
    { return (h->*m_ptr)(e); }


  private:
    // MEMBERS
    Action_t m_ptr;
  };



  /**
   * A class which implements Hierarchical State Machine.
   * Its services should be accessed through only its
   * derived class.
   */
  TC_EXPORT template <class D>
  class OpHsm
  {
  public:
    // TYPES
    typedef HsmState<D> State_t;
    typedef typename State_t::Action_t Action_t;

    //! Constants for this class
    enum {
      //! Maximum depth of the states
      MaxDepth = 8
    };    
    

    // ACCESSORS
    //! Is-in-state query
    bool isInState(State_t st);

    // MODIFIERS
    //! Setup HSM, execute initial transition
    void setup(const SmEvent* e = 0);
    //! Dispatch event
    void dispatch(const SmEvent* e); 

  protected:
    // CREATORS
    OpHsm(State_t st);
    virtual ~OpHsm();

    // MODIFIERS
    //! The top state: Ultimate root of the state hierarchy
    State_t top(const SmEvent*);

    //! Triggers the action of of a given state by sending to it
    //! a given signal.
    State_t trigger(State_t st, SmSignal_t sig);

    //! Initial state transition in a composite state.
    void init(State_t st) { m_state = st; }

    //! State transition to a target state.
    //! arg usecache indicates if the transition may change in run time
    //! and we should not use cached transitions.
    void tran(State_t target, bool usecache=false);

  private:

    // NOT ALLOWED
    OpHsm();
    OpHsm(const OpHsm&);
    void operator=(const OpHsm&);

    // TYPES
    // Path of entry from Target to the Least Common Ancestor (LCA)
    typedef Array<State_t, MaxDepth> EntryPath_t;

    // The edges of the path = source and target state
    struct PathEdge 
    {
      //! Constructor
      PathEdge(State_t c, State_t s, State_t d)
      {
        std::memset(this, 0, sizeof(PathEdge));
        cur = c;
        src = s;
        dst = d;
      }

      //! Comparison operator for PathEdge objects;
      bool operator<(const PathEdge& p) const
      { return 0 > std::memcmp(this, &p, sizeof(PathEdge));  }

      State_t cur; //!< Current state
      State_t src; //!< Transition source state
      State_t dst; //!< Destination (target) state
    };

    // The association of source-destination pair to entry path
    typedef std::map<PathEdge, EntryPath_t> EntryPathDict_t;

    // MEMBERS
    //! Currently active state.
    State_t m_state; 
    //! Source state during a transition.
    //! If the transition is inherited from a superstate, the 
    //! source of this transition will be different from the active state.
    State_t m_source;
    //! Entry Path Dictionary
    EntryPathDict_t m_epdict;
    
  }; // end class



} // end namespace


#if !defined(TC_USE_EXPORT) && !defined(TC_OPHSM_CPP)
# include "OpHsm.cpp"
#endif


#endif /* TC_OPHSM_HPP */
